package com.zhou.controller;

import com.zhou.dto.Result;
import com.zhou.dto.UserLogin;
import com.zhou.entity.Perms;
import com.zhou.entity.Role;
import com.zhou.entity.User;
import com.zhou.service.UserService;
import com.zhou.utils.JWTUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

/**
 * @author 周贵有
 * @date 2021/3/27
 */
@RestController
@RequestMapping("user")
public class UserController {

    @Autowired
    private UserService userService;

    @CrossOrigin
    @RequestMapping("login")
    public Result login(@RequestBody User user){

        String username = user.getAccount();
        String password = user.getPassword();
        //获取主体对象
        Subject subject = SecurityUtils.getSubject();
        try {
            //UsernamePasswordToken 是用来存储用户和密码的
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
            subject.login(token);

            String principal = (String) subject.getPrincipal();
            User user1 = userService.findByUserName(principal);
            //创建Map作为JWT的载荷信息载体
            Map<String,String> payload=new HashMap<>();
            payload.put("account",user1.getAccount());

            // 创建封装的登录数据类（UserLogin类型），对象名随意写
            UserLogin userLoginData = new UserLogin();
            String token1=JWTUtils.getToken(payload);
            userLoginData.setUser(user1);
            userLoginData.setFailure_time(JWTUtils.getFailure_time());
            userLoginData.setToken(token1);
            return Result.LOGIN_SUCCESS.setNewResult("登录成功",userLoginData);

        } catch (UnknownAccountException e) {
            return Result.LOGIN_ERROR.setErrorResult("用户名错误");
        } catch (IncorrectCredentialsException e) {
            return Result.LOGIN_ERROR.setErrorResult("密码错误");
        }
    }

    /**
     * 根据用户名获取该用户的权限
     */
    @CrossOrigin
    @GetMapping("permission")
    public Result permissions(String account){
        /**
         * 根据用户名查出拥有的权限
         */
        User user = userService.findRoleByUserName(account);
        List<Role> roles = user.getRoles();
        List<Perms> permissions;
        List<String> permission = new ArrayList<String>();
        // 根据账号的角色ID查出所有权限
        for (Role role:roles
        ) {
            int roleId = role.getId();
            permissions = userService.findPermsByRoleId(roleId);
            for (Perms perms:permissions){
                permission.add(perms.getPermsname());
            }
        }
        // 把权限名取出来放在String类型的集合里
        return Result.SUCCESS.setNewResult("",permission);
    }


    /**
     * 上传文件处理
     */
    @CrossOrigin
    @RequestMapping("upload")
    @ResponseBody
    public Map<String, Object> uploadToUser(@RequestParam("file") MultipartFile file, String token) {

        Map<String, Object> map = new HashMap<>();
        FileOutputStream out = null;
        try {
            // file.getOriginalFilename()包含了后缀
            String fileName = file.getOriginalFilename();
            // 获取文件后缀名
            String Suffix = fileName.substring(fileName.lastIndexOf("."));
            // 文件名为UUID+后缀（这里需要修改为其他获取名字算法然后进行拼接）
            fileName = UUID.randomUUID().toString()+ Suffix;



            // 为通过文件名为自己添加路径
            if (fileName.indexOf("\\") != -1) {
                fileName = fileName.substring(fileName.lastIndexOf("\\"));
            }
            // 获取文件存放的文件夹地址
            String filePath = "D:/element-UI/test/";
            File f = new File(filePath);
            if (!f.exists()) {
                f.mkdirs();// 不存在路径则进行文件夹的创建
            }

            // 重新自定义文件的名称
            filePath = filePath + fileName;
            out = new FileOutputStream(filePath);
            out.write(file.getBytes());
            out.flush();
            out.close();
            System.out.println(Suffix);
            System.out.println(filePath);
            map.put("error","");
            map.put("state",1);
//            Thread.sleep(10000);
            return map;
        } catch (Exception e) {
            map.clear();
            map.put("2", "error");
            return map;
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 下载文件，下载文件就不要通过axios，因为有拦截器在了，徒增麻烦
     */
    @RequestMapping("download11")
    @ResponseBody
    @CrossOrigin
    public void downloadLocal(HttpServletResponse response, String file) throws FileNotFoundException {

        // 下载本地文件
        // 文件的默认保存名
        Map<String, Object> map = new HashMap<>();
        String fileName = "hahaha.zip".toString();
        // 读到流中
        // 文件的存放路径(使用数据库，传入消息编号，根据消息编号查询任务结果上传后的路径，经过压缩包压缩后再把路径放到这里)
        String path= "D:/element-UI/"+file+".zip".toString();
        System.out.println(path);
        InputStream inStream = new FileInputStream(path);
        // 设置输出的格式
        response.reset();
        response.setHeader("Access-Control-Allow-Origin","*");
        response.setContentType("application/octet-stream");
        response.addHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
        // 循环取出流中的数据
        byte[] b = new byte[100];
        int len;
        try {
            while ((len = inStream.read(b)) > 0) {
                response.getOutputStream().write(b, 0, len);
            }
            inStream.close();
            map.put("error","");
            map.put("state",1);

        } catch (IOException e) {
            e.printStackTrace();
            map.put("error","");
            map.put("state",1);

        }


    }


    @GetMapping(value = "/download")
    public ResponseEntity<ByteArrayResource> downloadFile(String fileId, HttpServletRequest request) throws Exception {
        // 这里根据我给定的fileId来下载指定的文件，
        // 如果你想根据其他方式来下载指定文件的话，请自己修改业务逻辑
        // 1. 根据fileId从数据库中获取到指定的文件信息，包括文件名、文件存储地址等等。
        // 1.1 假设我已经获取到了文件信息。
        System.out.println("下载");
        String fileName = "hahaha.png";
        String filePath = "D:/element-UI/test";


        // 2. 解决下载的文件的文件名出现中文乱码
        String userAgent = request.getHeader("User-Agent");
        if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
            // IE浏览器
            fileName = java.net.URLEncoder.encode(fileName, "UTF-8");
        } else {
            // 非IE浏览器
            fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
        }

        // 3. 下载文件
        byte[] data = Files.readAllBytes(Paths.get(filePath+"/"+fileName));
        ByteArrayResource resource = new ByteArrayResource(data);

        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName)
                .contentType(MediaType.APPLICATION_OCTET_STREAM).contentLength(data.length)
                .body(resource);
    }

}
